//
//  ChatViewController.swift
//  test-ios
//
//  Created by wyz5204 on 2023/7/23.
//

import Foundation
import UIKit
import Reusable
import RxSwift
import MJRefresh

class ChatViewController : SimpleViewController<ChatViewModel> {
    
    
    private lazy var messageTableView = {
        let view = UITableView()
        view.dataSource = self
        view.delegate = self
        view.register(cellType: BaseMessageCell.self)
        
        view.register(cellType: TextSendMessageCell.self)
        view.register(cellType: TextReceiveMessageCell.self)
        
        view.mj_header = MJRefreshNormalHeader(refreshingBlock: { [weak self] in
            // 下拉加载更多 当前消息之前的历史消息
            self?.viewModel?.pullUpMessage()
        }).then({ header in
            header.setTitle("下拉刷新", for: .idle)
            header.setTitle("释放更新", for: .pulling)
            header.setTitle("正在刷新...", for: .refreshing)
            header.height = 44
        })
        
        view.mj_footer = MJRefreshBackNormalFooter(refreshingBlock: { [weak self] in
            // 上拉加载更多 当前消息的之后的最新消息
            self?.viewModel?.pullDownMessage()
        }).then({ footer in
            footer.setTitle("上拉加载", for: .idle)
            footer.setTitle("释放更新", for: .pulling)
            footer.setTitle("正在刷新...", for: .refreshing)
        })
        
        return view ;
    }()
    
    override func initView(_ contentView: UIView) {
        super.initView(contentView)
        messageTableView.addTo(contentView) { view in
            view.snp.makeConstraints { make in
                make.edges.equalToSuperview()
            }
        }
        
        self.navigationItem.titleView?.backgroundColor = .white
    }
    
    override func bindViewModel(_ viewModel: ChatViewModel) {
        
        let output = viewModel.transform(ChatViewModel.Input())
        
        // 刷新tableView
        output.updateTable.subscribe(onNext: { [weak self]_ in
            self?.messageTableView.reloadData()
        }).disposed(by: rx.disposeBag)
        
        // 结束上拉加载
        output.finishRefreshEvent.subscribe(onNext: { [weak self]_ in
            Logger.e(" 结束上拉加载 ")
            self?.messageTableView.mj_header?.endRefreshing()
        }).disposed(by: rx.disposeBag)
        
        // 结束下拉刷新
        output.finishReloadEvent.subscribe(onNext: { [weak self]_ in
            Logger.e(" 结束下拉刷新 ")
            self?.messageTableView.mj_footer?.endRefreshing()
        }).disposed(by: rx.disposeBag)
        
        // 自动滑动
        output.scrollTableToPosition.subscribe(onNext: { [weak viewModel , weak self] position in
            guard let viewModel else {
                return
            }
            guard let self else {
                return
            }
            
            Logger.e(" 进行动态的滑动 \(position)")
            
            if(position < 0){
                self.messageTableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
                return
            }
            if(position >= viewModel.messageDataSource.count){
                self.messageTableView.scrollToRow(at: IndexPath(row: viewModel.messageDataSource.count - 1, section: 0), at: .bottom, animated: true)
                return
            }
            let isTop = position < (viewModel.messageDataSource.count / 2)
            // 进行动画
            self.messageTableView.scrollToRow(at: IndexPath(row: position, section: 0), at: isTop ? .top : .bottom, animated: false)
            
        }).disposed(by: rx.disposeBag)
        
        // 设置名称
        self.navigationItem.title = viewModel.sessionBean.name
        
        // 设置 tableView
        
        //debug
#if DEBUG
        let debug = DebugViewHelper()
        debug.backgroundColor = .red
        debug.setTitleAndColor("测试", color: .white)
        debug.setDebug(DebugViewHelper.Callback(name: "下拉加载历史消息", call: {[weak self] in
            
            self?.messageTableView.mj_header?.beginRefreshing()
            
        }))
        debug.setDebug(DebugViewHelper.Callback(name: "上拉加载最新消息", call: {[weak self] in
            
            self?.messageTableView.mj_footer?.beginRefreshing()
            
        }))
        debug.setDebug(DebugViewHelper.Callback(name: "测试滑动到制定的seqId", call: {[weak self] in
            
            self?.viewModel?._pullMessage("1603288698027376640")
            
        }))
        debug.setDebug(DebugViewHelper.Callback(name: "测试滑动到制定的seqId 下", call: {[weak self] in
            
            self?.viewModel?._pullMessage("1603288698027376640" , isPullUp: false)
            
        }))
        debug.addTo(self.view) { view in
            view.snp.makeConstraints { make in
                make.centerY.equalToSuperview()
                make.right.equalToSuperview()
            }
        }
#endif
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        // 进行初始化界面数据
        viewModel?.initMessage()
    }
}

extension ChatViewController : UITableViewDataSource , UITableViewDelegate {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return viewModel?.messageDataSource.count ?? 0
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let bean = viewModel?.messageDataSource[indexPath.row] else {
            return tableView.dequeueReusableCell(for: indexPath , cellType: BaseMessageCell.self)
        }
        
        let messageType = ChatMessageType(rawValue: bean.messageType)
        let isSend = bean.from == viewModel?.mineCrmId
        
        let cell : BaseMessageCell
        switch (messageType , isSend){
        case (.Text, false):
            cell = tableView.dequeueReusableCell(for: indexPath , cellType: TextReceiveMessageCell.self)
        case (.Text, true):
            cell = tableView.dequeueReusableCell(for: indexPath , cellType: TextSendMessageCell.self)
        default :
            cell = tableView.dequeueReusableCell(for: indexPath , cellType: BaseMessageCell.self)
        }
        
        cell.initBinder(tableView, bean, indexPath)
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if let bean = viewModel?.messageDataSource[indexPath.row] {
            let messageType = ChatMessageType(rawValue: bean.messageType)
            let isSend = bean.from == viewModel?.mineCrmId
            
            Logger.e(" \(indexPath) \n \(try? bean.jsonString() ?? "current bean null" )" , "type:\(messageType) , \(isSend)" , "isSend : \(isSend)" , "mine : \(viewModel?.mineCrmId)")
            
        }
    }
    
}

class ChatViewModel : SimpleViewModel , MVVMTransform {
    
    // 进行初始化sessionId
    let sessionId : String
    let sessionBean : ChatSession
    let netModel : RDNetModel
    let mineCrmId : String = RDDBModel.shared().getCrmId()
    
    var messageDataSource = [ChatMessageBean]()
    
    let updateTable = PublishSubject<Void>()
    
    let finishRefreshEvent = PublishSubject<Void>()
    
    let finishReloadEvent = PublishSubject<Void>()
    
    let scrollTableToPosition = PublishSubject<Int>()
    
    init(_ session : ChatSession) {
        self.sessionId = session.sessionID
        self.sessionBean = session
        self.netModel = RDNetModel.shared
        super.init()
    }
    
    struct Input{
        
    }
    
    
    struct Output{
        let updateTable : PublishSubject<Void>
        let finishRefreshEvent : PublishSubject<Void>
        let finishReloadEvent : PublishSubject<Void>
        let scrollTableToPosition : PublishSubject<Int>
    }
    
    func transform(_ input: Input) -> Output {
        
        return Output(updateTable: updateTable , finishRefreshEvent: finishRefreshEvent , finishReloadEvent: finishReloadEvent , scrollTableToPosition: scrollTableToPosition)
    }
    
    func _pullMessage(_ targetSeqId : String , isPullUp : Bool = true){
        pullMessage(seqId: targetSeqId , isPullUp: isPullUp){[weak self]data in
            
            self?.messageDataSource.removeAll()
            self?.messageDataSource.append(contentsOf: data)
            
            if(isPullUp) {
                defer {
                    // 粗暴的设置
                    self?.finishRefreshEvent.onNext(())
                }
                self?.updateTable.onNext(())
                self?.scrollTableToPosition.onNext(0)
                return
            }
            
            defer {
                // 粗暴的设置
                self?.finishReloadEvent.onNext(())
            }
            self?.updateTable.onNext(())
            self?.scrollTableToPosition.onNext(data.count-1)
        }
    }
    
    func pullUpMessage(){
        let seqId = messageDataSource.isEmpty ? "" : messageDataSource.first!.seqId
        pullMessage(seqId: seqId , isPullUp: true){[weak self]data in
            defer {
                // 粗暴的设置
                self?.finishRefreshEvent.onNext(())
            }
            guard let self else{
                return
            }
            let beforeCount = self.messageDataSource.count
            self.messageDataSource.insert(contentsOf: data, at: 0)
            let afterCount = self.messageDataSource.count
            
            Logger.e("向上加载消息 ", beforeCount , afterCount ,afterCount - beforeCount - 1)
            self.updateTable.onNext(())
            if(beforeCount != afterCount){
                // 进行滑动一个指标位置
                self.scrollTableToPosition.onNext(afterCount - beforeCount - 1)
            }
        }
    }
    
    
    func pullDownMessage(){
        if (messageDataSource.isEmpty) {
            // 结束刷新
            self.finishReloadEvent.onNext(())
            return
        }
        pullMessage(seqId: messageDataSource.last!.seqId , isPullUp: false){[weak self] data in
            defer {
                // 粗暴的设置
                self?.finishReloadEvent.onNext(())
            }
            guard let self else{
                return
            }
            let beforeCount = self.messageDataSource.count
            self.messageDataSource.append(contentsOf: data)
            let afterCount = self.messageDataSource.count
            Logger.e("向下加载消息 ", beforeCount , afterCount ,afterCount - beforeCount + 1)
            
            self.updateTable.onNext(())
            // 进行滑动一个指标位置
            if(beforeCount != afterCount){
                self.scrollTableToPosition.onNext(beforeCount + 1)
            }
        }
    }
    
    func initMessage(){
        pullMessage(seqId: "" , isPullUp: true){[weak self]data in
            guard let self else{
                return
            }
            self.messageDataSource.append(contentsOf: data)
            self.updateTable.onNext(())
            // 进行滑动一个指标位置
            self.scrollTableToPosition.onNext(self.messageDataSource.count - 1)
        }
    }
    
    func pullMessage(seqId : String = "" , isPullUp : Bool = true , callback : @escaping  ([ChatMessageBean]) -> Void ){
        netModel.pullChatMessage(sessionId: sessionId, sessionType: sessionBean.type, seqId: seqId , upDown: isPullUp).subscribe(onSuccess: {response in
            Logger.e(response , "count = \(response.data?.count)")
            callback(response.data ?? [ChatMessageBean]())
        } , onFailure: { error in
            Logger.e(error)
            callback([ChatMessageBean]())
        }).disposed(by: rx.disposeBag)
    }
}
